/*
 * @Author: spring
 * @version:
 * @Date: 2022-09-07 14:17:43
 * @LastEditors: spring
 * @LastEditTime: 2022-09-17 23:55:53
 * @Descripttion: Com_tcp 的实现文件
 */

#include "../include/Com_tcp.h"
#define syserr(err)  \
    do               \
    {                \
        perror(err); \
        exit(-1);    \
    } while (0)

/**
 * @msg: 获取一个socket 监听套接字，
 * @param {char} *ip ：监听的IP地址
 * @param {int} port：监听的端口
 * @return {*} ：正确 返回一个监听套接字，错误返回-1
 */
int getListenfd(const char *ip, const int port)
{

    int fd = socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in server;

    if (fd < 0)
    {
        perror("socket cerate fail\n");
        return -1;
    }

    int opt = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) != 0)
        perror("setsockopt SO_REUSEADDR failed\n");

    memset(&server, 0, sizeof(sockaddr_in));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(ip);
    server.sin_port = htons(port);

    if (bind(fd, (sockaddr *)&server, sizeof(sockaddr)) != 0)
    {
        perror("bind failed");
        return -1;
    }

    if (listen(fd, LISTEN_LEN) != 0)
    {
        perror("listen failed");
        return -1;
    }

    return fd;
}


/**
 * @msg: 封装 命令数据到帧中。 帧由该函数开辟new 空间，出来需要外部释放。
 * @param {activate_car} data:数据结构体
 * @param {char} * & 封装之后的命令。
 * @return {*} 成功返回true 失败返回false
 */
bool packCmdData_activate_car(const struct activate_car data, char **COM)
{
    int size = sizeof(struct activate_car)+sizeof(int)+sizeof(long long)+sizeof(char);
    *COM = (char *) malloc(size);
    if(NULL == *COM) 
    {
        return false;
    }
    bzero(*COM,size);

    //将头存入
    char *p = *COM;
    int top = COM_TOP;
    memcpy((void*)*COM,(void*)&top,4);
    *COM += 4;

    //存入 数据的大小
    long long data_size = sizeof(struct activate_car);
    memcpy((void*)*COM,(void*)&data_size,8);
    *COM += 8;

    enum COM_CMD_TYPE one;
    one = CAR_BEHAVIOR;
    char c = one;
    memcpy((void*)*COM,(void*)&c,1);
    *COM += 1;

    struct activate_car DATA = data;
    memcpy((void*)*COM,(void*)&DATA,sizeof(struct activate_car));
    
    *COM = p;

    return true;
}

/**
 * @msg:小车环境信息封装函数
 * @param {activate_car} data
 * @param {char} *
 * @return {*}
 */
bool packCmdData_car_info(const struct car_info data, char **COM)
{
    int size = sizeof(struct car_info)+sizeof(int)+sizeof(long long)+sizeof(char);
    *COM = (char *)malloc(size);
    if(NULL == *COM)
    {
        return false;
    }
    bzero(*COM, size);

    char *p = *COM;
    int top = COM_TOP;
    memcpy((void*)*COM,(void*)&top,4);
    *COM += 4;

    long long data_size = sizeof(struct car_info);
    memcpy((void*)*COM,(void*)&data_size,8);
    *COM += 8;

    enum COM_CMD_TYPE one;
    one = ENV_INFO;
    char c = one ;
    memcpy((void*)*COM,(void*)&c,1);
    *COM += 1;

    struct car_info DATA = data;
    memcpy((void*)*COM,(void*)&DATA,sizeof(struct car_info));

    *COM = p;
    return true;

}

/**
 * @msg:
 * @param {trumpet} data
 * @param {char} *
 * @return {*}
 */
bool packCmdData_trumpet(const struct trumpet data, char **COM)
{
    int size = sizeof(struct trumpet)+sizeof(int)+sizeof(long long)+sizeof(char);
    *COM = (char *) malloc(size);
    if(NULL == *COM)
    {
        return false;
    }
    bzero(*COM, size);

    char *p = *COM;

    int top = COM_TOP;
    memcpy((void*)*COM,(void*)&top,4);
    *COM += 4;

    long long data_size = sizeof(struct trumpet);
    memcpy((void*)*COM,(void*)&data_size,8);
    *COM += 8;

    enum COM_CMD_TYPE one = TRUMPET;
    char c = one;
    memcpy((void*)*COM,(void*)&c,1);
    *COM += 1;

    struct trumpet DATA = data;
    memcpy((void*)*COM,(void*)&DATA,sizeof(struct trumpet));
    
    *COM = p;
    return true;
}

/**
 * @msg:摄像头数据封装
 * @param {trumpet} data
 * @param {char} *
 * @return {*}
 */
bool packCmdData_cam_t(const struct cam_t data, char **COM)
{
    int size = sizeof(struct cam_t)+sizeof(int)+sizeof(long long)+sizeof(char);
    *COM = (char *)malloc(size);
    if(NULL == *COM)
    {
        return false;
    }
    bzero(*COM, size);

    char *p = *COM;
    int top = COM_TOP;
    memcpy((void*)*COM,(void*)&top,4);
    *COM += 4;

    long long data_size = sizeof(struct cam_t);
    memcpy((void*)*COM,(void*)&data_size,8);
    *COM += 8;

    enum COM_CMD_TYPE one = VIDEO;
    char c = one ;
    memcpy((void*)*COM,(void*)&c,1);
    *COM += 1;

    struct cam_t DATA = data;
    memcpy((void*)*COM,(void*)&DATA,sizeof(struct cam_t));
    
    *COM = p;
    return true;

}

/**
 * @msg: 解析命令头
 * @param {activate_car} &data
 * @param {char} *COM
 * @return {*}成功返回 true，失败返回false
 */
bool unPackCmdHead(struct head *data,const char *COM)
{
    if(NULL == COM) 
    {
        return false;
    }
    data->data_type = *(int *)COM;
    data->size = *(long long *)(COM+4);
    data->cmd_type = *(char *)(COM+12);
    return true;
}

/**
 * @msg: 解析，帧中数据放到data中。
 * @param {activate_car} &data
 * @param {char} *COM
 * @return {*}成功返回 true，失败返回false
 */
bool unPackCmdData_activate_car(struct activate_car *data, const char *COM)
{
    if(NULL == COM)
    {
        return false;
    }
    struct activate_car *temp = (struct activate_car *)(COM + 13);
    data->degrees = temp->degrees;
    data->F = temp->F;
    return true;
}

/**
 * @msg:
 * @param {car_behavior} &data
 * @param {char} *COM
 * @return {*}
 */
bool unPackCmdData_car_info(struct car_info *data, const char *COM)
{
    if(NULL == COM)
    {
        return false;
    }
    struct car_info *tmp = (struct car_info *)(COM + 13);
    data->temp = tmp->temp;
    data->hum = tmp->hum;
    data->noise = tmp->noise;
    data->barrier = tmp->barrier;
    data->speed = tmp->speed;
    return true;
}

/**
 * @msg:
 * @param {trumpet} &data
 * @param {char} *COM
 * @return {*}
 */
bool unPackCmdData_trumpet(struct trumpet *data, const char *COM)
{
    if(NULL == COM)
    {
        return false;
    }
    struct trumpet *temp = (struct trumpet *)(COM + 13);
    data->mode = temp->mode;
    data->volume = temp->volume;
    data->HZ = temp->HZ;
    return true;
}

/**
 * @msg:摄像头数据解析
 * @param {trumpet} data
 * @param {char} *
 * @return {*}
 */
bool unpackCmdData_cam_t(struct cam_t *data,const char *COM)
{
    if(NULL == COM)
    {
        return false;
    }
    struct cam_t *temp = (struct cam_t *)(COM + 13);
    
    memcpy(data->pic_buf,temp->pic_buf,temp->pic_len);
    data->pic_len = temp->pic_len;
    
    return true;
}
